package com.rickpan.service.impl;

import com.rickpan.entity.Project;
import com.rickpan.entity.TeamMember;
import com.rickpan.exception.BusinessException;
import com.rickpan.repository.ProjectRepository;
import com.rickpan.repository.TeamMemberRepository;
import com.rickpan.service.ProjectService;
import com.rickpan.service.ProjectTaskService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * 项目服务实现类
 * 
 * @author RickPan Team
 * @since 2024-01-15
 */
@Service
@Transactional
public class ProjectServiceImpl implements ProjectService {

    private static final Logger logger = LoggerFactory.getLogger(ProjectServiceImpl.class);

    @Autowired
    private ProjectRepository projectRepository;

    @Autowired
    private TeamMemberRepository teamMemberRepository;

    @Autowired
    @Lazy
    private ProjectTaskService projectTaskService;

    @Override
    public Project createProject(Project project) {
        logger.info("创建项目: {}, 团队ID: {}", project.getName(), project.getTeamId());

        // 检查团队中是否存在同名项目
        if (projectRepository.existsByTeamIdAndName(project.getTeamId(), project.getName())) {
            throw new BusinessException("团队中已存在同名项目: " + project.getName());
        }

        // 设置初始状态
        if (project.getStatus() == null) {
            project.setStatus(Project.Status.PLANNING);
        }

        // 设置初始进度
        if (project.getProgress() == null) {
            project.setProgress(0);
        }

        // 保存项目
        return projectRepository.save(project);
    }

    @Override
    public Project updateProject(Project project) {
        logger.info("更新项目: {}, ID: {}", project.getName(), project.getId());

        // 检查项目是否存在
        Project existingProject = projectRepository.findById(project.getId())
                .orElseThrow(() -> new BusinessException("项目不存在: " + project.getId()));

        // 检查团队中是否存在同名项目（排除当前项目）
        if (!existingProject.getName().equals(project.getName()) &&
                projectRepository.existsByTeamIdAndNameExcludingId(
                        project.getTeamId(), project.getName(), project.getId())) {
            throw new BusinessException("团队中已存在同名项目: " + project.getName());
        }

        // 更新项目
        return projectRepository.save(project);
    }

    @Override
    public void deleteProject(Long projectId) {
        logger.info("删除项目: {}", projectId);

        // 检查项目是否存在
        if (!projectRepository.existsById(projectId)) {
            throw new BusinessException("项目不存在: " + projectId);
        }

        // 删除项目
        projectRepository.deleteById(projectId);
    }

    @Override
    @Transactional(readOnly = true)
    public Optional<Project> findById(Long projectId) {
        return projectRepository.findById(projectId);
    }

    @Override
    @Transactional(readOnly = true)
    public List<Project> findProjectsByTeam(Long teamId) {
        return projectRepository.findByTeamIdOrderByCreatedAtDesc(teamId);
    }

    @Override
    @Transactional(readOnly = true)
    public Page<Project> findProjectsByTeam(Long teamId, Pageable pageable) {
        return projectRepository.findByTeamIdOrderByCreatedAtDesc(teamId, pageable);
    }

    @Override
    @Transactional(readOnly = true)
    public List<Project> findProjectsByTeamAndStatus(Long teamId, Project.Status status) {
        return projectRepository.findByTeamIdAndStatusOrderByCreatedAtDesc(teamId, status);
    }

    @Override
    @Transactional(readOnly = true)
    public Page<Project> findProjectsByTeamAndStatus(Long teamId, Project.Status status, Pageable pageable) {
        return projectRepository.findByTeamIdAndStatusOrderByCreatedAtDesc(teamId, status, pageable);
    }

    @Override
    @Transactional(readOnly = true)
    public List<Project> findProjectsByManager(Long projectManagerId) {
        return projectRepository.findByProjectManagerIdOrderByCreatedAtDesc(projectManagerId);
    }

    @Override
    @Transactional(readOnly = true)
    public List<Project> findProjectsByManagerAndStatus(Long projectManagerId, Project.Status status) {
        return projectRepository.findByProjectManagerIdAndStatusOrderByCreatedAtDesc(projectManagerId, status);
    }

    @Override
    @Transactional(readOnly = true)
    public List<Project> searchProjects(Long teamId, String keyword) {
        return projectRepository.searchProjectsByTeam(teamId, keyword);
    }

    @Override
    @Transactional(readOnly = true)
    public Page<Project> searchProjects(Long teamId, String keyword, Pageable pageable) {
        return projectRepository.searchProjectsByTeam(teamId, keyword, pageable);
    }

    @Override
    @Transactional(readOnly = true)
    public List<Project> findActiveProjects(int limit) {
        return projectRepository.findActiveProjects(PageRequest.of(0, limit));
    }

    @Override
    @Transactional(readOnly = true)
    public List<Project> findProjectsDueSoon(int days) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime future = now.plusDays(days);
        return projectRepository.findProjectsDueSoon(now, future);
    }

    @Override
    @Transactional(readOnly = true)
    public List<Project> findOverdueProjects() {
        return projectRepository.findOverdueProjects(LocalDateTime.now());
    }

    @Override
    @Transactional(readOnly = true)
    public List<Project> findOverdueProjectsByTeam(Long teamId) {
        // 获取团队所有项目
        List<Project> projects = projectRepository.findByTeamIdAndStatusOrderByCreatedAtDesc(teamId, Project.Status.ACTIVE);
        
        // 筛选逾期项目
        LocalDateTime now = LocalDateTime.now();
        return projects.stream()
                .filter(p -> p.getEndDate() != null && p.getEndDate().isBefore(now))
                .toList();
    }

    @Override
    public void updateProjectProgress(Long projectId) {
        logger.info("更新项目进度: {}", projectId);

        // 检查项目是否存在
        Project project = projectRepository.findById(projectId)
                .orElseThrow(() -> new BusinessException("项目不存在: " + projectId));

        // 调用项目的updateProgress方法
        project.updateProgress();

        // 保存项目
        projectRepository.save(project);
    }

    @Override
    public void updateProjectProgress(Long projectId, Integer progress) {
        logger.info("手动更新项目进度: {}, 进度: {}%", projectId, progress);

        // 检查项目是否存在
        Project project = projectRepository.findById(projectId)
                .orElseThrow(() -> new BusinessException("项目不存在: " + projectId));

        // 设置进度
        project.setProgress(progress);

        // 保存项目
        projectRepository.save(project);
    }

    @Override
    public void updateProjectStatus(Long projectId, Project.Status status) {
        logger.info("更新项目状态: {}, 状态: {}", projectId, status);

        // 检查项目是否存在
        Project project = projectRepository.findById(projectId)
                .orElseThrow(() -> new BusinessException("项目不存在: " + projectId));

        // 更新状态
        project.setStatus(status);

        // 如果状态为已完成，设置进度为100%
        if (status == Project.Status.COMPLETED) {
            project.setProgress(100);
        }

        // 保存项目
        projectRepository.save(project);
    }

    @Override
    public void assignProjectManager(Long projectId, Long projectManagerId) {
        logger.info("分配项目经理: {}, 经理ID: {}", projectId, projectManagerId);

        // 检查项目是否存在
        Project project = projectRepository.findById(projectId)
                .orElseThrow(() -> new BusinessException("项目不存在: " + projectId));

        // 更新项目经理
        project.setProjectManagerId(projectManagerId);

        // 保存项目
        projectRepository.save(project);
    }

    @Override
    @Transactional(readOnly = true)
    public ProjectStatistics getProjectStatistics(Long teamId) {
        // 获取团队项目总数
        long totalProjects = projectRepository.countByTeamId(teamId);
        
        // 获取活跃项目数
        long activeProjects = projectRepository.countByTeamIdAndStatus(teamId, Project.Status.ACTIVE);
        
        // 获取已完成项目数
        long completedProjects = projectRepository.countByTeamIdAndStatus(teamId, Project.Status.COMPLETED);
        
        // 获取逾期项目数
        long overdueProjects = findOverdueProjectsByTeam(teamId).size();
        
        // 计算平均进度
        double averageProgress = 0;
        if (totalProjects > 0) {
            List<Project> projects = projectRepository.findByTeamIdOrderByCreatedAtDesc(teamId);
            averageProgress = projects.stream()
                    .mapToInt(Project::getProgress)
                    .average()
                    .orElse(0);
        }
        
        return new ProjectStatistics(totalProjects, activeProjects, completedProjects, 
                                   overdueProjects, averageProgress);
    }

    @Override
    @Transactional(readOnly = true)
    public boolean hasProjectManagePermission(Long projectId, Long userId) {
        // 检查项目是否存在
        Project project = projectRepository.findById(projectId)
                .orElseThrow(() -> new BusinessException("项目不存在: " + projectId));
        
        // 检查用户是否是项目经理
        if (project.getProjectManagerId() != null && project.getProjectManagerId().equals(userId)) {
            return true;
        }
        
        // 检查用户在团队中的角色
        Optional<TeamMember> teamMember = teamMemberRepository.findByTeamIdAndUserId(project.getTeamId(), userId);
        return teamMember.isPresent() && 
               (teamMember.get().getRole() == TeamMember.Role.OWNER || 
                teamMember.get().getRole() == TeamMember.Role.ADMIN);
    }

    @Override
    @Transactional(readOnly = true)
    public boolean hasProjectViewPermission(Long projectId, Long userId) {
        // 检查项目是否存在
        Project project = projectRepository.findById(projectId)
                .orElseThrow(() -> new BusinessException("项目不存在: " + projectId));
        
        // 检查用户是否是团队成员
        Optional<TeamMember> teamMember = teamMemberRepository.findByTeamIdAndUserId(project.getTeamId(), userId);
        return teamMember.isPresent() && teamMember.get().getStatus() == TeamMember.Status.ACTIVE;
    }
}
